using System;
using System.Collections.Generic;
using System.Text;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.FAS.Runtime.StateMachine.SPI;

namespace T.FAS.Runtime.StateMachine.Engine
{
    public class ActionController
    {
        public delegate TRecord ActionProcessEventHandler(TRecord record, TAction action, StateMachineMetadata metadata, Dictionary<string, object> extParams = null);
        private static ActionController current;
        private static object lckObj = new object();

        private ActionController()
        {
            Load();
        }

        public static ActionController Current
        {
            get
            {
                if (current == null)
                {
                    lock (lckObj)
                    {
                        if (current == null)
                            current = new ActionController();
                    }
                }
                return current;
            }
        }

        private Dictionary<string, ActionProcessEventHandler> handlers;
        private List<IActionProcess> sysDefault;
        private void Load()
        {
            handlers = new Dictionary<string, ActionProcessEventHandler>();
            sysDefault = new List<IActionProcess>();

            var emptyHandler = new EmptyActionProcess();
            handlers.Add(emptyHandler.Key, new ActionProcessEventHandler(emptyHandler.Do));
            sysDefault.Add(emptyHandler);

            var defaultHandler = new DefaultActionProcess();
            handlers.Add(defaultHandler.Key, new ActionProcessEventHandler(defaultHandler.Do));
            sysDefault.Add(defaultHandler);

            var copyHandler = new CopyActionProcess();
            handlers.Add(copyHandler.Key, new ActionProcessEventHandler(copyHandler.Do));
            sysDefault.Add(copyHandler);


            var expressionHandler = new ExpressionActionProcess();
            handlers.Add(expressionHandler.Key, new ActionProcessEventHandler(expressionHandler.Do));
        }

        /// <summary>
        /// 制定动作处理
        /// </summary>
        /// <param name="record"></param>
        /// <param name="actions"></param>
        /// <param name="metadata"></param>
        /// <returns></returns>
        public TRecord Do(TRecord record,List<TAction> actions, StateMachineMetadata metadata, Dictionary<string, object> extParams = null)
        {
            if (actions == null)
                return record;

            TRecord result = record;
            foreach (var action in actions)
            {
                if (action.ActionType == ActionType.System)
                {
                    var sysActionKey = action.ActionInfo ?? action.ActionInfoJson;
                    if(string.IsNullOrEmpty(sysActionKey))
                        throw new Exception(string.Format(CommonStringClass.ActionController_Do,metadata?.Code,action.ID));
                    if (handlers.ContainsKey(sysActionKey) == false)
                        throw new Exception(CommonStringClass.ActionController_Do1+ sysActionKey);
                    result = handlers[sysActionKey].Invoke(result, action, metadata, extParams);
                }
                else
                {
                    result = handlers[ExpressionActionProcess.CSTKEY].Invoke(result, action, metadata);
                }
            }
            return result;
        }

        /// <summary>
        /// 获取系统预制的动作
        /// </summary>
        /// <returns></returns>
        public List<IActionProcess> GetSysDefaultActions()
        {
            return sysDefault;
        }
    }
}
